package com.godyao.framework.beans.factory.support;


import com.godyao.framework.beans.factory.ConfigurableBeanFactory;
import com.godyao.framework.beans.factory.FactoryBean;
import com.godyao.framework.beans.factory.config.BeanDefinition;
import com.godyao.framework.beans.factory.config.BeanPostProcessor;
import com.godyao.framework.utils.ClassUtils;
import com.godyao.framework.utils.StringValueResolver;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 抽象类定义模板方法
 * @author missw
 */
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();

    private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();

    /**
     * String resolvers to apply e.g. to annotation attribute values
     */
    private final List<StringValueResolver> embeddedValueResolvers = new ArrayList<>();


    /**
     * com.godyao.framework.beans.factory.BeanFactory#getBean(java.lang.String) 的实现
     * @param beanName
     * @return
     */
    @Override
    public Object getBean(String beanName) {
        return doGetBean(beanName, null);

    }

    @Override
    public Object getBean(String beanName, Object... args) {
        return doGetBean(beanName, args);

    }


    @Override
    public <T> T getBean(String beanName, Class<T> tClass) {
        return (T)getBean(beanName);
    }


    private <T> T doGetBean(String beanName, final Object[] args) {
        boolean flag = false;
        if (beanName.startsWith("&")) {
            flag = true;
            beanName = beanName.substring(1);
        }
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null) {
            if (flag) return (T)sharedInstance;
            // 如果是FactoryBean,则需要调用它的getObject()方法
            return (T)getObjectFromBeanInstance(sharedInstance, beanName);
        }
        BeanDefinition beanDefinition = getBeanDefinition(beanName);
        return (T) createBean(beanName, beanDefinition, args);
    }

    private Object getObjectFromBeanInstance(Object beanInstance, String beanName) {
        if (!(beanInstance instanceof FactoryBean)) {
            return beanInstance;
        }
        Object objectFactoryBean = getCachedObjectFactoryBean(beanName);
        if (objectFactoryBean == null) {
            objectFactoryBean = getObjectFromFactoryBean((FactoryBean) beanInstance, beanName);
        }
        return objectFactoryBean;
    }

    /**
     * 定义模板，具体由子类实现 (AbstractAutowireCapableBeanFactory)
     * @param beanDefinition
     * @return
     */
    protected abstract Object createBean(String beanName, BeanDefinition beanDefinition, Object[] args);

    /**
     * 定义模板，具体由子类实现 (DefaultListableBeanFactory)
     * @param beanName
     * @return
     */
    protected abstract BeanDefinition getBeanDefinition(String beanName);

    public List<BeanPostProcessor> getBeanPostProcessors() {
        return this.beanPostProcessors;
    }

    @Override
    public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
        // 移除调旧的
        this.beanPostProcessors.remove(beanPostProcessor);
        // 始终将新的放在最后面
        this.beanPostProcessors.add(beanPostProcessor);
    }

    @Override
    public ClassLoader getBeanClassLoader() {
        return this.beanClassLoader;
    }

    @Override
    public void setBeanClassLoader(ClassLoader beanClassLoader) {
        this.beanClassLoader = (beanClassLoader != null ? beanClassLoader : ClassUtils.getDefaultClassLoader());
    }

    @Override
    public void addEmbeddedValueResolver(StringValueResolver valueResolver) {
        this.embeddedValueResolvers.add(valueResolver);
    }

    @Override
    public String resolveEmbeddedValue(String value) {
        String result = value;
        for (StringValueResolver resolver : this.embeddedValueResolvers) {
            result = resolver.resolveStringValue(result);
        }
        return result;
    }

}
